import { Page, Locator } from '@playwright/test';

/**
 * UI交互助手 - 解决UI自动化测试中的常见交互问题
 * 包括模态框处理、文件上传、异步操作等
 */
export class UIInteractionHelper {
  private page: Page;
  private defaultTimeout: number = 10000;

  constructor(page: Page) {
    this.page = page;
  }

  /**
   * 智能点击 - 处理可能被模态框或其他元素遮挡的点击
   */
  async smartClick(selector: string | Locator, options: {
    timeout?: number;
    force?: boolean;
    waitForStable?: boolean;
  } = {}): Promise<void> {
    const { timeout = this.defaultTimeout, force = false, waitForStable = true } = options;
    
    const element = typeof selector === 'string' ? this.page.locator(selector) : selector;
    
    // 等待元素可见
    await element.waitFor({ state: 'visible', timeout });
    
    // 等待元素稳定（避免动画干扰）
    if (waitForStable) {
      await this.page.waitForTimeout(500);
    }
    
    // 滚动到元素位置
    await element.scrollIntoViewIfNeeded();
    
    // 检查是否有遮挡元素
    if (!force) {
      const isClickable = await element.isEnabled();
      if (!isClickable) {
        console.warn('元素不可点击，尝试强制点击');
      }
    }
    
    try {
      await element.click({ force, timeout });
    } catch (error) {
      console.warn(`普通点击失败: ${error.message}，尝试JavaScript点击`);
      await element.evaluate(el => (el as HTMLElement).click());
    }
  }

  /**
   * 处理模态框 - 自动检测和处理各种类型的模态框
   */
  async handleModal(action: 'close' | 'confirm' | 'cancel' = 'close', timeout: number = 5000): Promise<boolean> {
    const modalSelectors = [
      '.ant-modal',
      '.ant-drawer', 
      '[role="dialog"]',
      '.modal',
      '.popup'
    ];
    
    for (const selector of modalSelectors) {
      const modal = this.page.locator(selector);
      
      if (await modal.isVisible({ timeout: 1000 })) {
        console.log(`检测到模态框: ${selector}`);
        
        switch (action) {
          case 'close':
            // 尝试多种关闭方式
            const closeSelectors = [
              `${selector} .ant-modal-close`,
              `${selector} .ant-drawer-close`,
              `${selector} [aria-label="Close"]`,
              `${selector} .close`,
              `${selector} .btn-close`
            ];
            
            let closed = false;
            for (const closeSelector of closeSelectors) {
              const closeBtn = this.page.locator(closeSelector);
              if (await closeBtn.isVisible({ timeout: 500 })) {
                await closeBtn.click();
                closed = true;
                break;
              }
            }
            
            if (!closed) {
              // 尝试ESC键
              await this.page.keyboard.press('Escape');
            }
            break;
            
          case 'confirm':
            const confirmSelectors = [
              `${selector} .ant-btn-primary`,
              `${selector} .btn-primary`,
              `${selector} .confirm`,
              `${selector} .ok`
            ];
            
            for (const confirmSelector of confirmSelectors) {
              const confirmBtn = this.page.locator(confirmSelector);
              if (await confirmBtn.isVisible({ timeout: 500 })) {
                await confirmBtn.click();
                break;
              }
            }
            break;
            
          case 'cancel':
            const cancelSelectors = [
              `${selector} .ant-btn:has-text("取消")`,
              `${selector} .ant-btn:has-text("Cancel")`,
              `${selector} .btn-cancel`,
              `${selector} .cancel`
            ];
            
            for (const cancelSelector of cancelSelectors) {
              const cancelBtn = this.page.locator(cancelSelector);
              if (await cancelBtn.isVisible({ timeout: 500 })) {
                await cancelBtn.click();
                break;
              }
            }
            break;
        }
        
        // 等待模态框消失
        await modal.waitFor({ state: 'hidden', timeout }).catch(() => {
          console.warn('模态框未在预期时间内消失');
        });
        
        return true;
      }
    }
    
    return false;
  }

  /**
   * 智能文件上传 - 处理各种文件上传场景
   */
  async smartFileUpload(filePath: string, options: {
    triggerSelector?: string;
    fileInputSelector?: string;
    waitForUpload?: boolean;
    uploadTimeout?: number;
  } = {}): Promise<boolean> {
    const {
      triggerSelector,
      fileInputSelector = 'input[type="file"]',
      waitForUpload = true,
      uploadTimeout = 30000
    } = options;
    
    try {
      // 如果有触发按钮，先点击
      if (triggerSelector) {
        await this.smartClick(triggerSelector);
        await this.page.waitForTimeout(1000);
      }
      
      // 查找文件输入元素
      const fileInput = this.page.locator(fileInputSelector);
      
      // 等待文件输入元素出现
      await fileInput.waitFor({ timeout: 10000 });
      
      // 设置文件
      await fileInput.setInputFiles(filePath);
      console.log(`已设置文件: ${filePath}`);
      
      if (waitForUpload) {
        // 等待上传完成的各种信号
        const uploadIndicators = [
          '.ant-upload-list-item-done',
          '.upload-success',
          '.file-uploaded',
          '[data-testid="upload-success"]'
        ];
        
        let uploadComplete = false;
        const startTime = Date.now();
        
        while (!uploadComplete && (Date.now() - startTime) < uploadTimeout) {
          for (const indicator of uploadIndicators) {
            if (await this.page.locator(indicator).isVisible({ timeout: 1000 })) {
              uploadComplete = true;
              break;
            }
          }
          
          if (!uploadComplete) {
            await this.page.waitForTimeout(1000);
          }
        }
        
        if (!uploadComplete) {
          console.warn('未检测到上传完成信号，但继续执行');
        }
      }
      
      return true;
    } catch (error) {
      console.error(`文件上传失败: ${error.message}`);
      return false;
    }
  }

  /**
   * 等待异步操作完成 - 处理各种异步加载场景
   */
  async waitForAsyncOperation(options: {
    loadingSelectors?: string[];
    successSelectors?: string[];
    errorSelectors?: string[];
    timeout?: number;
  } = {}): Promise<'success' | 'error' | 'timeout'> {
    const {
      loadingSelectors = ['.ant-spin', '.loading', '.spinner'],
      successSelectors = ['.ant-message-success', '.success', '.completed'],
      errorSelectors = ['.ant-message-error', '.error', '.failed'],
      timeout = 30000
    } = options;
    
    const startTime = Date.now();
    
    while ((Date.now() - startTime) < timeout) {
      // 检查错误状态
      for (const errorSelector of errorSelectors) {
        if (await this.page.locator(errorSelector).isVisible({ timeout: 500 })) {
          return 'error';
        }
      }
      
      // 检查成功状态
      for (const successSelector of successSelectors) {
        if (await this.page.locator(successSelector).isVisible({ timeout: 500 })) {
          return 'success';
        }
      }
      
      // 检查是否还在加载
      let stillLoading = false;
      for (const loadingSelector of loadingSelectors) {
        if (await this.page.locator(loadingSelector).isVisible({ timeout: 500 })) {
          stillLoading = true;
          break;
        }
      }
      
      if (!stillLoading) {
        // 没有加载指示器，可能已完成
        await this.page.waitForTimeout(1000);
        return 'success';
      }
      
      await this.page.waitForTimeout(1000);
    }
    
    return 'timeout';
  }

  /**
   * 自动登录助手
   */
  async autoLogin(credentials: {
    email?: string;
    password?: string;
    token?: string;
  } = {}): Promise<boolean> {
    const {
      email = 'admin@example.com',
      password = '123456',
      token
    } = credentials;
    
    try {
      // 如果有token，直接设置
      if (token) {
        await this.page.evaluate((token) => {
          localStorage.setItem('admin_token', token);
        }, token);
        await this.page.reload({ waitUntil: 'networkidle' });
        return true;
      }
      
      // 检查是否有调试token按钮
      const debugTokenBtn = this.page.locator('button:has-text("设置调试Token")');
      if (await debugTokenBtn.isVisible({ timeout: 3000 })) {
        await debugTokenBtn.click();
        await this.page.reload({ waitUntil: 'networkidle' });
        return true;
      }
      
      // 查找登录表单
      const emailInput = this.page.locator('input[type="email"], input[name="email"]');
      const passwordInput = this.page.locator('input[type="password"]');
      
      if (await emailInput.isVisible({ timeout: 3000 })) {
        await emailInput.fill(email);
        await passwordInput.fill(password);
        
        const loginBtn = this.page.locator('button:has-text("登录"), button[type="submit"]');
        await loginBtn.click();
        
        // 等待登录完成
        await this.page.waitForTimeout(3000);
        return true;
      }
      
      return false;
    } catch (error) {
      console.error(`自动登录失败: ${error.message}`);
      return false;
    }
  }

  /**
   * 截图并保存证据
   */
  async captureEvidence(name: string, fullPage: boolean = true): Promise<void> {
    const timestamp = Date.now();
    const filename = `test-results/evidence-${name}-${timestamp}.png`;
    
    await this.page.screenshot({ 
      path: filename, 
      fullPage,
      animations: 'disabled'
    });
    
    console.log(`已保存截图: ${filename}`);
  }
}